package abel.wlmr.model.unit;

import abel.util.HexString;
import abel.wlmr.model.WlmrBaseUnit;
import abel.wlmr.model.WlmrException;
import abel.wlmr.model.type.PortType;
import abel.wlmr.model.type.TransCtrlField;
import abel.wlmr.model.type.WaitPacketTimeoutField;
import io.netty.buffer.ByteBuf;

/**
 * B.5.14.1.2.1 F1：透明转发
 * 数据体格式见表 B.213。
 * 表B.212 透明转发数据单元格式
 * 数据内容 数据格式 单位 字节数
 * 终端通信端口号 BIN 1
 * 透明转发通信控制字 BS8 1
 * 透明转发接收等待报文超时时间 BS8 10ms 或 1s 1
 * 透明转发接收等待字节超时时间 BIN 10ms 1
 * 透明转发内容字节数 k BIN 字节 2
 * 透明转发内容 k
 * ——终端通信端口号：数据范围 1～31。
 * ——透明转发通信控制字定义如下图 B.52。
 * D7 D6 D5 D4 D3 D2 D1 D0
 * Baud（bps）： 0～7 依次表示
 * 300， 600， 1200， 2400， 4800， 7200， 9600，
 * 19200
 * 0/1：
 * 1/ 2 停止位
 * 0/1：
 * 无/有校验
 * 0/1：
 * 偶/奇校验
 * 0～3：
 * 5-8 位数
 * 图B.52 透明转发通信控制字定义
 * ——透明转发接收等待报文超时时间：
 * ● D7：按位表示本字节 D0～D6 编码组成的数据的单位，置“0”： 10ms，置“1”： s。
 * ● D6～D0：编码表示透明转发接收等待报文超时时间的数值，数值范围 0～127。
 * 
 * @author Abel
 *
 */
public class Afn10F1Unit extends WlmrBaseUnit {
    private static final short MIN_LENGTH = 1 + 1 + 1 + 1 + 2;

    private PortType port;

    private TransCtrlField transCtrl;

    private WaitPacketTimeoutField waitPacketTimeout;

    private short waitByteTimeout;

    private int lf;

    private HexString data;

    public Afn10F1Unit() {
        super();
    }

    public Afn10F1Unit(short guessedLen) {
        super(guessedLen);
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#appendBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        buf.writeByte(port.getValue());
        buf.writeByte(transCtrl.getValue());
        buf.writeByte(waitPacketTimeout.getValue());
        buf.writeShortLE(waitByteTimeout);
        buf.writeShortLE(lf);
        buf.writeBytes(data.getBs());

        return buf;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#parseBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        if (checkBuffer(buf) < 0) {
            return -1;
        }

        int len = MIN_LENGTH;
        {
            ByteBuf dup = buf.duplicate();
            dup.skipBytes(1 + 1 + 1 + 1);
            lf = dup.readUnsignedShortLE();
            len += lf;
            if (getGuessedLength() < len) {
                throw new WlmrException("not enough bytes for 0F.1 body");
            }
        }

        port = PortType.findPortByValue(buf.readByte());
        transCtrl = new TransCtrlField();
        transCtrl.parseValue(buf.readByte());

        waitPacketTimeout = new WaitPacketTimeoutField();
        waitPacketTimeout.parseValue(buf.readByte());

        waitByteTimeout = (short) (buf.readByte() & 0xFF);
        buf.skipBytes(2);
        data = new HexString(buf, lf);

        return len;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.WlmrDataPart#getMinLength()
     */
    @Override
    public int getMinLength() {
        return MIN_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#getFinalLen()
     */
    @Override
    public short getFinalLen() {
        short len = MIN_LENGTH;

        len += lf;

        return len;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return String.format("{port:%s, transCtrl:%s, waitPacketTimeout:%s, waitByteTimeout:%s, lf:%s, data:%s}", port,
            transCtrl, waitPacketTimeout, waitByteTimeout, lf, data);
    }
}
